package com.macro.mall.util.httpclient;

import com.macro.mall.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;

/**
 * 
 * @author wchen4
 *  支持http https协议
 */
public class CallRestUtil {

	private static Logger logger = LoggerFactory.getLogger(CallRestUtil.class);

	private static int CONNECTION_TIMEOUT = 30000;

	/**
	 *  https 忽略证书
	 */
	private final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	};

	private static void trustAllHosts() {
		// Create a trust manager that does not validate certificate chains
		TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
			@Override
			public X509Certificate[] getAcceptedIssuers() {
				return new X509Certificate[]{};
			}

			@Override
			public void checkClientTrusted(X509Certificate[] chain, String authType) {
			}

			@Override
			public void checkServerTrusted(X509Certificate[] chain, String authType) {
			}
		}};
		// Install the all-trusting trust manager
		try {
			SSLContext sc = SSLContext.getInstance("TLS");
			sc.init(null, trustAllCerts, new java.security.SecureRandom());
			HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
		}
	}


	/**
	 * Set header parameters into request header
	 * @param httpConn
	 * @param method
	 * @param headerParams
	 */
	protected static void setRequestHeader(HttpURLConnection httpConn,
										   String method, Map<String, String> headerParams) {
		if (headerParams != null) {
			Iterator<String> it = headerParams.keySet().iterator();
			String key, value;
			while (it.hasNext()) {
				key = it.next();
				value = headerParams.get(key);
				if (value == null) {
					value = "";
				}
				httpConn.setRequestProperty(key, value);
			}
		}
		try {
			httpConn.setRequestMethod(method);
		} catch (ProtocolException e) {
			logger.error(e.getMessage(),e);
		}
	}


	/**
	 * Call rest service
	 * @param serviceURL
	 * @param method
	 * @param headerParams
	 * @param body
	 * @return
	 * @throws BusinessException
	 */
	public static com.macro.mall.util.httpclient.CallResult doCall(String serviceURL,
                                                            String method, Map<String, String> headerParams, String accept, String content, String body, Integer connectTimeout) throws BusinessException {
		long startTime = System.currentTimeMillis();
		HttpURLConnection httpConn;
		try {
			URL url = new URL(serviceURL);
			if ("https".equalsIgnoreCase(url.getProtocol())) {
				trustAllHosts();
				HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
				https.setHostnameVerifier(DO_NOT_VERIFY);
				httpConn = https;
			} else {
				httpConn = (HttpURLConnection) url.openConnection();
			}
			setRequestHeader(httpConn, method, headerParams);
			httpConn.setDoOutput(true);
			httpConn.setUseCaches(false);
			httpConn.setRequestProperty("Cache-Control","no-cache");
			if(connectTimeout == null){
				connectTimeout = CONNECTION_TIMEOUT;
			}
			httpConn.setConnectTimeout(connectTimeout);
			httpConn.setReadTimeout(connectTimeout);
			if (accept == null) {
				accept = "application/json;charset=utf-8";
			}
			if (content == null) {
				content = "application/json;charset=utf-8";
			}
			httpConn.setRequestProperty("Accept", accept);
			httpConn.setRequestProperty("Content-Type", content);
			if (body != null && !"".equals(body)) {
				DataOutputStream dos = new DataOutputStream(
						httpConn.getOutputStream());
				dos.write(body.getBytes("utf-8"));
//				dos.writeBytes(body);
				dos.flush();
				dos.close();
			} else {
				httpConn.connect();
			}
			int responseCode = httpConn.getResponseCode();
			String str;
			InputStream input;
			if (responseCode == HttpURLConnection.HTTP_OK || responseCode==HttpURLConnection.HTTP_CREATED) {
				input = httpConn.getInputStream();
			} else {
				input = httpConn.getErrorStream();
			}
			BufferedReader br = new BufferedReader(new InputStreamReader(input, "utf-8"));
			str = br.readLine();
			br.close();
			httpConn.disconnect();

			long endTime = System.currentTimeMillis();
			long costTime = endTime - startTime;

			logger.debug(serviceURL +" cost time:" + costTime+"||rescode:"+responseCode+"||result:"+str);
			if (costTime > 2000) {// cost time more than two second
				// send alarm info to CM
			}
            com.macro.mall.util.httpclient.CallResult cr = new com.macro.mall.util.httpclient.CallResult();
			cr.setStatus(responseCode);
			cr.setBody(str);
			cr.setCosttime(costTime);
			return cr;
		} catch (IOException e) {
			throw new BusinessException(e);
		}

	}


	/**
	 * callSendMap
	 * @param serviceUrl
	 * @param method
	 * @param headerParams
	 * @param formParams
	 * @param accept
	 * @param content
	 * @return
	 * @throws BusinessException
	 */
	public static com.macro.mall.util.httpclient.CallResult callSendMap(String serviceUrl,
                                                                 String method, Map<String, String> headerParams,
                                                                 Map<String, String> formParams, String accept, String content, Integer connectTimeout) throws BusinessException {
		StringBuilder body = new StringBuilder();
		if (formParams != null) {
			Iterator<String> it = formParams.keySet().iterator();
			String key, value;
			while (it.hasNext()) {
				key = it.next();
				try {
					value = formParams.get(key);
					if (value != null) {
						body.append(key + "=" + URLEncoder.encode(formParams.get(key), "utf-8"));
					} else {
						body.append(key + "=");
					}
				} catch (UnsupportedEncodingException e) {
					logger.error("url encode failure,{}",e.getMessage());
				}
				if (it.hasNext()) {
					body.append("&");
				}
			}
		}
		return doCall(serviceUrl, method, headerParams,
				accept,content, body.toString(),connectTimeout);
	}

	/**
	 * callSendJsonObject
	 * @param serviceUrl
	 * @param method
	 * @param headerParams
	 * @param body
	 * @Param accept
	 * @return
	 * @throws BusinessException
	 */
	public static com.macro.mall.util.httpclient.CallResult callSendJsonObject(String serviceUrl,
                                                                        String method, Map<String, String> headerParams,
                                                                        String body, String accept, String content, Integer connectTimeout) throws BusinessException {
		return doCall(serviceUrl, method, headerParams,
				accept,content, body,connectTimeout);
	}

	/**
	 * 读取txt文件的内容
	 * @param file 想要读取的文件对象
	 * @return 返回文件内容
	 */
	public static String txt2String(File file){
		StringBuilder result = new StringBuilder();
		try{
			BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件
			String s;
			while((s = br.readLine())!=null){//使用readLine方法，一次读一行
				result.append(s).append("\\n");
			}
			br.close();
		}catch(Exception e){
			logger.error(e.getMessage(),e);
		}
		return result.toString();
	}



	public static void main(String[] args) {
//		try {
//			//查询
//			CallResult callResult = CallRestUtil.callSendJsonObject("https://10.124.132.5:9006/console", "POST", null, null, null, null);
//			if(callResult.getStatus()==200|| callResult.getStatus() == 201){
//				System.out.println(callResult.getBody());
//			}
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
	}
	
}
